package com.nixsolutions.dao;

import com.nixsolutions.bean.Role;
import java.util.List;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;

/**
 *
 * @author yakimovich
 */
public class HibernateRoleDao implements RoleDao {

    /**
     * Create logger.
     */
    private static org.apache.commons.logging.Log logger = LogFactory.getLog(HibernateRoleDao.class);
    @Autowired
    private SessionFactory sessionFactory;

    public HibernateRoleDao() {
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    @Override
    public void create(Role role) {

        if (role == null) {
            throw new NullPointerException();
        }

        Session session = null;
        Transaction transaction = null;

        try {
            session = sessionFactory.openSession();
            transaction = session.getTransaction();
            transaction.begin();

            session.save(role);

            transaction.commit();
        } catch (Exception e) {
            logger.error(this, e);
            transaction.rollback();
            throw new RuntimeException(e);
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }

    @Override
    public void update(Role role) {

        if (role == null) {
            throw new NullPointerException();
        }

        Session session = null;
        Transaction transaction = null;

        try {
            session = sessionFactory.openSession();
            transaction = session.getTransaction();
            transaction.begin();

            session.update(role);

            transaction.commit();
        } catch (Exception e) {
            logger.error(this, e);
            transaction.rollback();
            throw new RuntimeException(e);
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }

    @Override
    public void remove(Role role) {

        if (role == null) {
            throw new NullPointerException();
        }

        Session session = null;
        Transaction transaction = null;
        try {
            session = sessionFactory.openSession();
            transaction = session.getTransaction();
            transaction.begin();

            session.delete(role);

            transaction.commit();
        } catch (Exception e) {
            logger.error(this, e);
            transaction.rollback();
            throw new RuntimeException(e);
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }

    @Override
    public Role findByName(String name) {

        if (name == null) {
            throw new NullPointerException();
        }

        Role role = null;

        Session session = null;
        Transaction transaction = null;

        try {
            session = sessionFactory.openSession();
            transaction = session.getTransaction();
            transaction.begin();

            Criteria criteria = session.createCriteria(Role.class);
            criteria.add(Restrictions.eq("name", name));
            List<Role> roles = criteria.list();
            if (roles.isEmpty()) {
                throw new IllegalArgumentException();
            }
            role = roles.get(0);

            transaction.commit();
        } catch (Exception e) {
            logger.error(this, e);
            transaction.rollback();
            throw new RuntimeException(e);
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
        return role;
    }
}